package co.gov.medellin.ssti.sub.model.dao.impl;

import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcDaoSupport;
import org.springframework.stereotype.Repository;

import co.gov.medellin.ssti.sub.model.dao.RenovarDAO;
import co.gov.medellin.ssti.sub.model.vo.AtributoVO;
import co.gov.medellin.ssti.sub.model.vo.BeneficiarioVO;
import co.gov.medellin.ssti.sub.model.vo.RenovarVO;

@Repository
public class RenovarDAOImpl2 extends NamedParameterJdbcDaoSupport implements
		RenovarDAO {

	private static final String SELECT_SUBP_ATR_BENEFICIARIO_BY_SBPR_CODIGO = "SELECT CODIGO, NOMBRE, TIPO_DATO, TIPO_ATRIBUTO "
			+ "FROM TCS_BEN_SUBP_ATR_BENEFICIARIO WHERE SBPR_CODIGO = :SBPR_CODIGO AND VIGENCIA='A' AND CAMPO_A2 IS NULL";

	private static final String SELECT_BENEFICIARIO_ATRIBUTO_VALOR_NUM_ATR = "SELECT VALOR_NUM_ATR "
			+ " valor FROM TCS_BEN_BENEFICIARIO_ATRIBUTO "
			+ "WHERE SAB_CODIGO = :SAB_CODIGO AND BEN_CODIGO = :BEN_CODIGO ";

	private static final String SELECT_BENEFICIARIO_ATRIBUTO_VALOR_FEC_ATR = "SELECT TO_CHAR(VALOR_FEC_ATR,'DD/MM/YYYY') "
			+ " valor FROM TCS_BEN_BENEFICIARIO_ATRIBUTO "
			+ " WHERE SAB_CODIGO = :SAB_CODIGO AND BEN_CODIGO = :BEN_CODIGO ";

	private static final String SELECT_BENEFICIARIO_ATRIBUTO_VALOR_CAR_ATR = "SELECT VALOR_CAR_ATR "
			+ " valor FROM TCS_BEN_BENEFICIARIO_ATRIBUTO "
			+ " WHERE SAB_CODIGO = :SAB_CODIGO AND BEN_CODIGO = :BEN_CODIGO ";

	private static final String SELECT_BENEFICIO_ATRIBUTO_VALOR_NUM_ATR = "SELECT VALOR_NUM_ATR "
			+ " valor FROM TCS_BEN_BENEFICIO_ATRIBUTO WHERE BOT_CODIGO = :BOT_CODIGO "
			+ " AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_BENEFICIO_ATRIBUTO_VALOR_FEC_ATR = "SELECT TO_CHAR(VALOR_FEC_ATR,'DD/MM/RRRR') "
			+ " valor FROM TCS_BEN_BENEFICIO_ATRIBUTO WHERE BOT_CODIGO = :BOT_CODIGO "
			+ " AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_BENEFICIO_ATRIBUTO_VALOR_CAR_ATR = "SELECT VALOR_CAR_ATR "
			+ " valor FROM TCS_BEN_BENEFICIO_ATRIBUTO WHERE BOT_CODIGO = :BOT_CODIGO "
			+ " AND SAB_CODIGO = :SAB_CODIGO ";

	private static final String SELECT_MAX_COD_BENEFICIO_OTORGADO_BY_SUBP_COD_BEN_COD = "SELECT MAX(CODIGO) codbot, SEDE_CODIGO sede FROM TCS_BEN_BENEFICIO_OTORGADO "
			+ " WHERE SBPR_CODIGO = :SBPR_CODIGO AND BEN_CODIGO = :BEN_CODIGO "
			+ " AND FECHA_BENEFICIO=(SELECT MAX(FECHA_BENEFICIO) FROM TCS_BEN_BENEFICIO_OTORGADO "
			+ " WHERE SBPR_CODIGO = :SBPR_CODIGO AND BEN_CODIGO = :BEN_CODIGO ) "
			+ " GROUP BY SEDE_CODIGO";

	private static final String SELECT_MAX_COD_BENEFICIO_OTORGADO_EMPRESA_BY_SUBP_COD_BEN_COD = "SELECT MAX(CODIGO) codbot, SEDE_CODIGO sede FROM TCS_BEN_BENEFICIO_OTORGADO "
			+ " WHERE SBPR_CODIGO = :SBPR_CODIGO AND CAMPO_N3 = :CAMPO_N3 "
			+ " AND FECHA_BENEFICIO=(SELECT MAX(FECHA_BENEFICIO) FROM TCS_BEN_BENEFICIO_OTORGADO "
			+ " WHERE SBPR_CODIGO = :SBPR_CODIGO AND CAMPO_N3 = :CAMPO_N3 ) "
			+ " GROUP BY SEDE_CODIGO";

	private static final String SELECT_COD_BENEFICIO_OTORGADO_BY_CRITERIA = "SELECT CODIGO FROM TCS_BEN_BENEFICIO_OTORGADO "
			+ " WHERE SBPR_CODIGO = :SBPR_CODIGO AND BEN_CODIGO = :BEN_CODIGO "
			+ " AND SEDE_CODIGO = :SEDE_CODIGO AND CAMPO_A1 IS NULL";

	public Collection<AtributoVO> findAtributosSubpro(Long codeSubprograma) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		namedParameters.put("SBPR_CODIGO", codeSubprograma);

		List<AtributoVO> lAtributos = getNamedParameterJdbcTemplate().query(
				SELECT_SUBP_ATR_BENEFICIARIO_BY_SBPR_CODIGO, namedParameters,
				new RowMapper<AtributoVO>() {

					public AtributoVO mapRow(ResultSet rst, int rowNum)
							throws SQLException {
						AtributoVO vo = new AtributoVO();
						vo.setCodatributo(rst.getString("CODIGO"));
						vo.setNombre(rst.getString("NOMBRE"));
						vo.setTipodato(rst.getString("TIPO_DATO"));
						vo.setTipoatributo(rst.getString("TIPO_ATRIBUTO"));
						return vo;
					}
				});

		return lAtributos;
	}

	public String findBeneficiarioAtri(String tipoDato, Long codeBene,
			Long codeAtri) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String consulta = "";
		String strValor = null;
		if (tipoDato.equals("N")) {
			consulta = SELECT_BENEFICIARIO_ATRIBUTO_VALOR_NUM_ATR;
		} else if (tipoDato.equals("F")) {
			consulta = SELECT_BENEFICIARIO_ATRIBUTO_VALOR_FEC_ATR;
		} else {
			consulta = SELECT_BENEFICIARIO_ATRIBUTO_VALOR_CAR_ATR;
		}

		namedParameters.put("SAB_CODIGO", codeAtri);
		namedParameters.put("BEN_CODIGO", codeBene);

		try {
			strValor = getNamedParameterJdbcTemplate().queryForObject(consulta,
					namedParameters, String.class);
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO: throw?
		}

		return strValor;
	}

	// TODO: return resultSet.
	public RenovarVO findBeneficioAtri(String tipoDato, Long codeBeneOtor,
			Long codeAtri) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String consulta = "";
		if (tipoDato.equals("N")) {
			consulta = SELECT_BENEFICIO_ATRIBUTO_VALOR_NUM_ATR;
		} else if (tipoDato.equals("F")) {
			consulta = SELECT_BENEFICIO_ATRIBUTO_VALOR_FEC_ATR;
		} else {
			consulta = SELECT_BENEFICIO_ATRIBUTO_VALOR_CAR_ATR;
		}

		namedParameters.put("BOT_CODIGO", codeBeneOtor);
		namedParameters.put("SAB_CODIGO", codeAtri);

		try {
			return getNamedParameterJdbcTemplate().queryForObject(consulta,
					namedParameters, new RowMapper<RenovarVO>() {

						public RenovarVO mapRow(ResultSet rs, int rowNum)
								throws SQLException {
							RenovarVO vo = new RenovarVO();
							vo.setValor(rs.getString("valor"));
							return vo;
						}
					});
		} catch (IncorrectResultSizeDataAccessException e) {
			return null;
		}
	}

	public List<String> findBeneficioOtorgado(Long codeSubpro, Long codeBene) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		// SELECT_MAX_COD_BENEFICIO_OTORGADO_BY_SUBP_COD_BEN_COD
		namedParameters.put("SBPR_CODIGO", codeSubpro);
		namedParameters.put("BEN_CODIGO", codeBene.longValue());
		namedParameters.put("SBPR_CODIGO", codeSubpro.longValue());
		namedParameters.put("BEN_CODIGO", codeBene.longValue());

		List<String> lretornar = new LinkedList<String>();
		List<Map<String, Object>> rows = getNamedParameterJdbcTemplate()
				.queryForList(
						SELECT_MAX_COD_BENEFICIO_OTORGADO_BY_SUBP_COD_BEN_COD,
						namedParameters);
		for (Map<String, Object> row : rows) {
			BigDecimal codBot = (BigDecimal) row.get("codbot");
			BigDecimal sede = (BigDecimal) row.get("sede");
			if (codBot != null) {
				lretornar.add(Long.toString(codBot.longValueExact()));
			}
			if (sede != null) {
				lretornar.add(Long.toString(sede.longValueExact()));
			}
		}

		return lretornar;
	}

	public List<String> findBeneficioOtorgadoEmpresa(Long codeSubpro,
			Long codeEmpresa) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		// SELECT_MAX_COD_BENEFICIO_OTORGADO_BY_SUBP_COD_BEN_COD
		namedParameters.put("SBPR_CODIGO", codeSubpro);
		namedParameters.put("CAMPO_N3", codeEmpresa);
		System.out
				.println("query: "
						+ SELECT_MAX_COD_BENEFICIO_OTORGADO_EMPRESA_BY_SUBP_COD_BEN_COD);
		System.out.println("sbpr_codigo: " + codeSubpro);
		System.out.println("campo_n3: " + codeEmpresa);
		List<String> lretornar = new LinkedList<String>();
		List<Map<String, Object>> rows = getNamedParameterJdbcTemplate()
				.queryForList(
						SELECT_MAX_COD_BENEFICIO_OTORGADO_EMPRESA_BY_SUBP_COD_BEN_COD,
						namedParameters);
		for (Map<String, Object> row : rows) {
			BigDecimal codBot = (BigDecimal) row.get("codbot");
			BigDecimal sede = (BigDecimal) row.get("sede");
			if (codBot != null) {
				lretornar.add(Long.toString(codBot.longValueExact()));
			}
			if (sede != null) {
				lretornar.add(Long.toString(sede.longValueExact()));
			}
		}

		return lretornar;
	}

	public void findBeneOtorDeshabilitar(Long codeSubpro, Long codeBene,
			Long codeSede) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		namedParameters.put("SBPR_CODIGO", codeSubpro);
		namedParameters.put("BEN_CODIGO", codeBene);
		namedParameters.put("SEDE_CODIGO", codeSede);
		System.out.println("(SELECT_COD_BENEFICIO_OTORGADO_BY_CRITERIA[ "
				+ codeSubpro + "," + codeBene + "," + codeSede + "]: "
				+ SELECT_COD_BENEFICIO_OTORGADO_BY_CRITERIA);
		try {
			int codBeneOtor = getNamedParameterJdbcTemplate().queryForObject(
					SELECT_COD_BENEFICIO_OTORGADO_BY_CRITERIA, namedParameters,
					Integer.class);
			updateBeneotorCampoA1(codBeneOtor);
		} catch (IncorrectResultSizeDataAccessException e) {
			// TODO: handle exception
		}
	}

	public List<BeneficiarioVO> findBeneficiarios(Long codeSubpro, Long codeSede) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String SEL = " SELECT DISTINCT bot.BEN_CODIGO codebene,ben.PRIMER_NOMBRE nom1bene,ben.SEGUNDO_NOMBRE nom2bene, "
				+ " ben.PRIMER_APELLIDO ape1bene, ben.SEGUNDO_APELLIDO ape2bene, ben.TIPO_DOCUMENTO tipodoc, "
				+ " ben.NUMERO_DOCUMENTO numdoc, TO_CHAR "
				+ " ((SELECT MAX(FECHA_BENEFICIO) "
				+ " FROM TCS_BEN_BENEFICIO_OTORGADO bot1,TCS_BEN_BENEFICIARIO ben1 "
				+ " WHERE bot1.SBPR_CODIGO = :bot1.SBPR_CODIGO AND bot1.SEDE_CODIGO = :bot1.SEDE_CODIGO "
				+ " AND bot1.BEN_CODIGO=ben1.codigo),'DD/MM/RRRR')fecha "
				+ " FROM TCS_BEN_BENEFICIO_OTORGADO bot,TCS_BEN_BENEFICIARIO ben, "
				+ " TCS_BEN_SUBPROGRAMA sub "
				+ " WHERE bot.SBPR_CODIGO = :bot.SBPR_CODIGO AND  bot.SEDE_CODIGO = :bot.SEDE_CODIGO "
				+ " AND ben.CODIGO = bot.BEN_CODIGO "
				+ " AND sub.CODIGO = bot.SBPR_CODIGO "
				+ " AND (CASE WHEN DECODE(bot.CAMPO_A1,'I',-1,TO_NUMBER(SYSDATE - (SELECT MAX(CAMPO_F1) "
				+ "                                                               FROM TCS_BEN_BENEFICIO_OTORGADO "
				+ "                                                               WHERE SBPR_CODIGO = :SBPR_CODIGO "
				+ "                                                               AND BEN_CODIGO=ben.CODIGO "
				+ "                                                               AND SEDE_CODIGO = :SEDE_CODIGO "
				+ " ))) "
				+ " >= TO_NUMBER(nvl(sub.CAMPO_A3,0)+1) "
				+ " THEN 'Si' ELSE 'No' END) = 'Si' ";

		List<BeneficiarioVO> lbeneficiarios = new LinkedList<BeneficiarioVO>();

		namedParameters.put("bot1.SBPR_CODIGO", codeSubpro);
		namedParameters.put("bot1.SEDE_CODIGO", codeSede);
		namedParameters.put("bot.SBPR_CODIGO", codeSubpro);
		namedParameters.put("bot.SEDE_CODIGO", codeSede);
		namedParameters.put("SBPR_CODIGO", codeSubpro);
		namedParameters.put("SEDE_CODIGO", codeSede);

		List<Map<String, Object>> rows = getNamedParameterJdbcTemplate()
				.queryForList(SEL, namedParameters);
		for (Map<String, Object> row : rows) {
			BeneficiarioVO benevo = new BeneficiarioVO();
			benevo.setCode((Long) (row.get("codebene")));
			benevo.setNombre1((String) row.get("nom1bene"));
			benevo.setNombre2((String) row.get("nom2bene"));
			benevo.setPrimerApellido((String) row.get("ape1bene"));
			benevo.setSegundoApellido((String) row.get("ape2bene"));
			if (((String) row.get("tipodoc")).equals("O")) {
				benevo.setTipoDocumento("NO TIENE");
			} else if (((String) row.get("tipodoc")).equals("C")) {
				benevo.setTipoDocumento("CEDULA DE CIUDADANIA");
			} else if (((String) row.get("tipodoc")).equals("E")) {
				benevo.setTipoDocumento("CEDULA DE EXTRANJERIA");
			} else if (((String) row.get("tipodoc")).equals("N")) {
				benevo.setTipoDocumento("NIT");
			} else if (((String) row.get("tipodoc")).equals("P")) {
				benevo.setTipoDocumento("PASAPORTR");
			} else if (((String) row.get("tipodoc")).equals("R")) {
				benevo.setTipoDocumento("REGISTRO CIVIL");
			} else if (((String) row.get("tipodoc")).equals("T")) {
				benevo.setTipoDocumento("TARJETA DE IDENTIDAD");
			} else if (((String) row.get("tipodoc")).equals("I")) {
				benevo.setTipoDocumento("NIP");
			} else if (((String) row.get("tipodoc")).equals("U")) {
				benevo.setTipoDocumento("NUIP");
			} else if (((String) row.get("tipodoc")).equals("S")) {
				benevo.setTipoDocumento("NISE");
			} else if (((String) row.get("tipodoc")).equals("A")) {
				benevo.setTipoDocumento("CABILDO");
			}
			benevo.setNumeroDocumento((String) row.get("numdoc"));
			benevo.setFechaNacimiento((String) row.get("fecha"));
			lbeneficiarios.add(benevo);
		}
		return lbeneficiarios;
	}

	private void updateBeneotorCampoA1(int codeBeneotor) {
		Map<String, Object> namedParameters = new HashMap<String, Object>();

		String query = "UPDATE TCS_BEN_BENEFICIO_OTORGADO SET "
				+ "CAMPO_A1 = 'I' WHERE CODIGO = :CODIGO ";

		namedParameters.put("CODIGO", codeBeneotor);
		getNamedParameterJdbcTemplate().update(query, namedParameters);
	}

}
